package io.potato.ts.service;

import io.potato.core.AppException;
import io.potato.ts.common.Constants;
import io.potato.ts.domain.Contacts;
import io.potato.ts.domain.ContactsLink;
import io.potato.ts.domain.User;
import io.potato.ts.repository.ContactsLinkRepository;
import io.potato.ts.repository.ContactsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import io.potato.core.CrudService;
import io.potato.ts.domain.ContactsGroup;
import io.potato.ts.repository.ContactsGroupRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


/**
 * 通讯录群组服务类
 * 
 * @author timl
 *
 * <p>2019-01-07 15:13:58</p>
 */
@Service
@Transactional
public class ContactsGroupService extends CrudService<ContactsGroup, Integer> {

	@Autowired
	private ContactsGroupRepository repository;

	@Autowired
	private ContactsLinkRepository linkRepository;

	@Autowired
	private ContactsRepository contactsRepository;

	@Override
	protected JpaRepository<ContactsGroup, Integer> getRepository() {
		return repository;
	}

	/**
	 * 查询用户个人通讯录群组
	 * @param userId 用户ID
	 * @return  通讯录群组列表
	 */
	public List<ContactsGroup> findByUser(Integer userId) {
		return repository.findByUser(userId);
	}

	/**
	 * 查询指定节点下的个人通讯录群组
	 * @param userId  用户ID
	 * @param parentId  父群组ID
	 * @return
	 */
	public List<ContactsGroup> findByUser(Integer userId, Integer parentId) {
		if (parentId == null) {
			return repository.findByUser(userId);
		} else {
			return repository.findByUser(userId, parentId);
		}
	}

	/**
	 * 查询单位共享的通讯录群组
	 * @param organId  单位ID
	 * @return
	 */
	public List<ContactsGroup> findShare(Integer organId) {
		return repository.findShare(organId);
	}

	/**
	 * 查询单位共享的通讯录群组
	 * @param organId  单位ID
	 * @return
	 */
	public List<ContactsGroup> findShare(Integer organId, Integer parentId) {
		if(parentId == null) {
			return repository.findShare(organId);
		} else {
			return repository.findShare(organId, parentId);
		}
	}

	public void saveContracts(User user, Integer groupId, List<Contacts> contactsList) {
		Integer userId = user.getId();
		Integer organId = user.getOrganId();

		Optional<ContactsGroup> groupOptional = repository.findById(groupId);
		if (!groupOptional.isPresent()) {
			throw new AppException("通讯录群组不存在");
		}

		ContactsGroup group = groupOptional.get();
		Integer type = group.getType();
		if (Constants.GroupType.PRIVATE.equals(type)) {
			if (!userId.equals(group.getUserId())) {
				throw new AppException("通讯录群组不属于此用户");
			}
		} else {
			if (!organId.equals(group.getOrganId())) {
				throw new AppException("通讯录群组不属于此单位");
			}
		}

		for (Contacts contacts : contactsList) {
			contacts.setType(type);
			contacts.setUserId(userId);
			contacts.setOrganId(organId);
			contacts.setUserCode(user.getUserCode());
		}

		contactsRepository.saveAll(contactsList);

		List<ContactsLink> linkList = new ArrayList<>();
		for (Contacts contacts : contactsList) {
			ContactsLink link = new ContactsLink();
			link.setGroupId(groupId);
			link.setContractsId(contacts.getId());
			if (Constants.GroupType.PRIVATE.equals(type)) {
				link.setUserId(userId);
			} else {
				link.setOrganId(organId);
			}
			linkList.add(link);
		}

		linkRepository.saveAll(linkList);


	}

	/**
	 * 添加联系人到个人群组， 已存在的会忽略
	 * @param userId  用户ID
	 * @param groupId  个人群组ID
	 * @param contactIds  联系人ID
	 */
	public void addContacts(Integer userId, Integer groupId, List<Integer> contactIds) {

		checkAndGet(userId, groupId);

		List<ContactsLink> linkList = new ArrayList<>();

		for (Integer id : contactIds) {
			int count = linkRepository.countByGroupIdAndContractsId(groupId, id);
			if (count == 0) {
				ContactsLink link = new ContactsLink();
				link.setGroupId(groupId);
				link.setContractsId(id);
				link.setUserId(userId);
				linkList.add(link);
			}
		}

		if (linkList.size() > 0) {
			linkRepository.saveAll(linkList);
		}
	}

    /**
     * 添加联系人到共享群组
     * @param organId  单位ID
     * @param groupId  群组ID
     * @param contactIds  联系人ID
     */
    public void addShareContacts(Integer organId, Integer groupId, List<Integer> contactIds) {
        checkAndGetShareGroup(organId, groupId);
        List<ContactsLink> linkList = new ArrayList<>();

        for (Integer id : contactIds) {
            int count = linkRepository.countByGroupIdAndContractsId(groupId, id);
            if (count == 0) {
                ContactsLink link = new ContactsLink();
                link.setGroupId(groupId);
                link.setContractsId(id);
                link.setOrganId(organId);
                linkList.add(link);
            }
        }

        if (linkList.size() > 0) {
            linkRepository.saveAll(linkList);
        }
    }

	/**
	 * 删除个人群组下的联系人
	 * @param userId  用户ID
	 * @param groupId  群组ID
	 * @param contactIds  联系人ID
	 */
	public void deleteContacts(Integer userId, Integer groupId, List<Integer> contactIds) {
		checkAndGet(userId, groupId);
		linkRepository.deleteByContactsId(groupId, contactIds);
		// 删除不属于任何群组的联系人
		contactsRepository.deleteUnused(contactIds);
	}

    /**
     * 删除共享群组下的联系人
     * @param organId  单位ID
     * @param groupId   群组ID
     * @param contactIds  联系人ID
     */
    public void deleteShareContacts(Integer organId, Integer groupId, List<Integer> contactIds) {
        checkAndGetShareGroup(organId, groupId);
        linkRepository.deleteByContactsId(groupId, contactIds);
		// 删除不属于任何群组的联系人
        contactsRepository.deleteUnused(contactIds);
    }

	/**
	 * 删除个人群组以及关联的联系人
	 * @param userId 用户ID
	 * @param groupId  个人群组ID
	 */
	public void deleteGroup(Integer userId, Integer groupId) {
		checkAndGet(userId, groupId);
		checkChildGroup(groupId);

		deleteById(groupId);
		linkRepository.deleteByGroupId(groupId);
		contactsRepository.deleteUnused(groupId);
	}

    /**
     * 删除共享群组以及相关的联系人
     * @param organId  单位ID
     * @param groupId  群组ID
     */
    public void deleteShareGroup(Integer organId, Integer groupId) {
        checkAndGetShareGroup(organId, groupId);
        checkChildGroup(groupId);

        deleteById(groupId);
        linkRepository.deleteByGroupId(groupId);
		contactsRepository.deleteUnused(groupId);
    }

	/**
	 * 查询子群组数量
	 * @param groupId
	 * @return
	 */
	public Integer getChildCount(Integer groupId) {
    	return repository.countByParentId(groupId);
	}

	private void checkChildGroup(Integer groupId) {
		if (getChildCount(groupId) > 0) {
			throw new AppException("当前群组有子群组");
		}
	}

	private ContactsGroup checkAndGet(Integer userId, Integer groupId) {
		if (groupId.equals(0)) {
			ContactsGroup cg0 = new ContactsGroup();
			return cg0;
		}

		Optional<ContactsGroup> cg = findById(groupId);
		if (!cg.isPresent()) {
			throw new AppException("通讯录群组不存在");
		}

		ContactsGroup group = cg.get();
		if (!userId.equals(group.getUserId())) {
			throw new AppException("通讯录群组不属于此用户");
		}

		return group;
	}

    private ContactsGroup checkAndGetShareGroup(Integer organId, Integer groupId) {
        if (groupId.equals(-1)) {
            ContactsGroup cg0 = new ContactsGroup();
            return cg0;
        }

        Optional<ContactsGroup> cg = findById(groupId);
        if (!cg.isPresent()) {
            throw new AppException("通讯录群组不存在");
        }

        ContactsGroup group = cg.get();
        if (!organId.equals(group.getOrganId())) {
            throw new AppException("通讯录群组不属于此单位");
        }

        return group;
    }

}
